﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Castle.Core;
using Castle.Windsor;
using Castle.MicroKernel;
using Castle.Windsor.Configuration.Interpreters;

namespace AncientLand.Common
{
    public sealed class IocContainer
    {
        static private object _synRoot = new Object();
        private IWindsorContainer windsor;

        private IKernel _kernel;
        public IKernel Kernel
        {
            get { return _kernel; }
        }

        private static IocContainer _instance;
        public static IocContainer Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_synRoot)
                    {
                        if (_instance == null)
                        {
                            _instance = new IocContainer();
                        }
                    }

                }
                return IocContainer._instance;
            }
        }

        /// <summary>
        /// Reset the singleton
        /// </summary>
        static public void Reset()
        {
            _instance = null;
        }

        // Construction Method. Initialization IOC.
        private IocContainer()
        {
            try
            {
                //IOC containers establishment, and through the most dynamic configuration file by adding components.
                Castle.Core.Resource.ConfigResource source = new Castle.Core.Resource.ConfigResource();
                XmlInterpreter interpreter = new XmlInterpreter(source);
                windsor = new WindsorContainer(interpreter);
                _kernel = windsor.Kernel;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }


        /// Returns a component instance by the type of service.
        public T Resolve<T>()
        {
            return (T)_kernel[typeof(T)];
        }

        /// Returns a component instance by the service name.
        public object Resolve(Type service)
        {
            return _kernel[service];
        }

        /// Returns a component instance by the type of service.
        public T Resolve<T>(String key)
        {
            return (T)_kernel[key];
        }

        /// Returns a component instance by the service name.
        public object Resolve(String key)
        {
            return _kernel[key];
        }

        /// Returns a component instance by the service name.
        public object Resolve(String key, IDictionary arguments)
        {
            return windsor.Resolve(key, arguments);
        }

        /// Returns a component instance by the service name.
        public T Resolve<T>(String key, IDictionary arguments)
        {
            return windsor.Resolve<T>(key, arguments);
        }

        /// Returns a component instance by the service name.
        public T Resolve<T>(IDictionary arguments)
        {
            return windsor.Resolve<T>(arguments);
        }

        public void AddComponentWithLifestyle(string key, Type classType, LifestyleType liftstyle)
        {
            windsor.AddComponentWithLifestyle(key, classType, liftstyle);
        }

        public void AddComponentWithLifestyle(string key, Type classType, Type serviceType, LifestyleType liftstyle)
        {
            windsor.AddComponentWithLifestyle(key, classType, serviceType, liftstyle);
        }

        public void AddComponentWithLifestyle<T>(string key, LifestyleType liftstyle)
        {
            windsor.AddComponentWithLifestyle<T>(key, liftstyle);
        }

        public void AddComponent<T>()
        {
            windsor.AddComponent<T>();
        }
        public void AddComponent<T>(string key)
        {
            windsor.AddComponent<T>(key);
        }
        public void AddComponent(string key, Type classType)
        {
            windsor.AddComponent(key, classType);
        }
        public void AddComponent(string key, Type serveiceType, Type classType)
        {
            windsor.AddComponent(key, serveiceType, classType);
        }

        public void ReleaseComponent(object instance)
        {
            _kernel.ReleaseComponent(instance);
        }
        /// Release resource that be container used.
        public void Dispose()
        {
            _kernel.Dispose();
            windsor.Dispose();
        }
    }

}
